#include "FileUtil.h"
#include <filesystem>
#include <fstream>
#include <iostream>
#include <tuple>

char* FileUtil::readFile(std::string& file_name){
    std::ifstream file(file_name);
    file.seekg(0, std::ios::end);
	int fileLength = file.tellg();

	file.seekg(0, std::ios::beg);

	char* buffer = new char[fileLength + 1];
	file.read(buffer, fileLength);
	buffer[fileLength] = '\0';
    return buffer;
}

std::vector<std::string> FileUtil::readFileLines(std::string& file, char delim){
    std::ifstream ss(file);
    std::string item;
    std::vector<std::string> elems;
    while (std::getline(ss, item, delim)) {
        if (!item.empty()) {
            elems.push_back(item);
        }
    }
    return elems;
}

std::vector<std::string> FileUtil::readDir(std::string& dir,std::string& extension){

    auto ret = std::vector<std::string>();
    std::filesystem::path p(dir);
    if(std::filesystem::is_directory(p)){
        for(std::filesystem::path elem : std::filesystem::directory_iterator(p)){
            if(elem.extension()==extension ){
                ret.push_back(dir+'/'+elem.filename().string());
            }
         }
    }
    else{
        std::cout<<"not directory"<<std::endl;
    }
    return ret;
}

std::vector<std::string> FileUtil::readDirRecurs(std::string& dir,std::string& extension){

    auto ret = std::vector<std::string>();
    std::filesystem::path p(dir);
    if(std::filesystem::is_directory(p)){
        for(std::filesystem::path elem : std::filesystem::directory_iterator(p)){
            if(elem.extension()==extension ){
                ret.push_back(dir+'/'+elem.filename().string());
            }else{
                std::string new_path = elem.string();
                std::cout<<"new path:"<<new_path<<std::endl;
                if(std::filesystem::is_directory(new_path)){
                    auto ret2 = readDirRecurs(new_path, extension);
                    for(auto f:ret2){
                        ret.push_back(f);
                    }
                    std::cout<<"YYY"<<std::endl;
                }else{
                    std::cout<<"NNN"<<std::endl;
                }
             }
        }
    }
    else{
        std::cout<<"not directory:"<<p.filename()<<std::endl;
    }
    return ret;
}

std::vector<std::string> FileUtil::vimdoc(std::string& file_name){
   //std::string file_name = "/data/data/com.termux/files/usr/share/nvim/runtime/doc/api.txt";
   auto lines = readFileLines(file_name, '\n');
   bool is_in_doc = false;
   std::vector<std::string>  codes;
   std::string code;
   int i = 0;
   for(auto line:lines){
    i++; // debug used
    // cancel at start
    int len = line.size();
    if(is_in_doc && len > 0 && (line[0] !=' ' || line[0] == '\t') ){
        is_in_doc = false;
        if(code.size()>0){
           codes.push_back(code); 
           code = "";
        }
    }
    if(is_in_doc){
        code.append("\n");
        code.append(line);
    }
    if(len == 1 && line[0] =='>' || len >2 && line[len -1] == '>' && line[len -2] ==' ' ){
        is_in_doc = true;
    }
   }
    if(code.size()>0){
       codes.push_back(code); 
    }
    return codes;
}

std::vector<std::tuple<std::string, std::string>> FileUtil::mdcodes(std::string& file_name){
   //std::string 
   // file_name = "/data/data/com.termux/files/home/wiki/cpp/cpp-docs/docs/standard-library/tuple-functions.md";
   auto lines = readFileLines(file_name, '\n');
   std::cout<<lines.size()<<std::endl;
   bool is_in_doc = false;
   std::vector<std::tuple<std::string,std::string>>  codes;
   std::string code;
   std::string pre_code;
   int i = 0;
   for(auto line:lines){
    i++; // debug used
    // std::cout<<line<<std::endl;
    int len = line.size();
    if(is_in_doc && len > 2 && (line[0] =='`' && line[1] == '`' && line[2] == '`') ){
        is_in_doc = false;
        if(code.size()>0){
           codes.push_back(std::make_tuple(pre_code, code)); 
           code = "";
        }
    }
    else if(is_in_doc && (len<1 || len >0 && line[0]!='`')){
        code.append("\n");
        code.append(line);
    }
    else if(!is_in_doc && len > 2 && line[0] =='`' && line[1] == '`' && line[2] =='`' ){
        is_in_doc = true;
    }else{
        if(line != ""){
            pre_code = line;
        }
    }
   }
    if(code.size()>0){
       codes.push_back(std::make_tuple(pre_code, code)); 
    }
    return codes;
}
